package cn.com.ayqu.module.erp.service.sale;

import cn.com.ayqu.framework.common.enums.CommonStatusEnum;
import cn.com.ayqu.framework.common.pojo.PageResult;
import cn.com.ayqu.framework.common.util.collection.MapUtils;
import cn.com.ayqu.framework.common.util.object.BeanUtils;
import cn.com.ayqu.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.com.ayqu.module.erp.controller.admin.sale.vo.customer.ErpCustomerMorePageReqVO;
import cn.com.ayqu.module.erp.controller.admin.sale.vo.customer.ErpCustomerMoreRespVO;
import cn.com.ayqu.module.erp.controller.admin.sale.vo.customer.ErpCustomerPageReqVO;
import cn.com.ayqu.module.erp.controller.admin.sale.vo.customer.ErpCustomerSaveReqVO;
import cn.com.ayqu.module.erp.dal.dataobject.sale.ErpCustomerCarNumberDO;
import cn.com.ayqu.module.erp.dal.dataobject.sale.ErpCustomerDO;
import cn.com.ayqu.module.erp.dal.mysql.sale.ErpCustomerCarNumberMapper;
import cn.com.ayqu.module.erp.dal.mysql.sale.ErpCustomerMapper;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.util.*;

import static cn.com.ayqu.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.com.ayqu.framework.common.util.collection.CollectionUtils.*;
import static cn.com.ayqu.module.erp.enums.ErrorCodeConstants.CUSTOMER_NOT_ENABLE;
import static cn.com.ayqu.module.erp.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS;

/**
 * ERP 客户 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class ErpCustomerServiceImpl implements ErpCustomerService {

    @Resource
    private ErpCustomerMapper customerMapper;

    @Resource
    private ErpCustomerCarNumberMapper customerCarNumberMapper;

    @Override
    @Transactional
    public Long createCustomer(ErpCustomerSaveReqVO createReqVO) {
        // 插入
        ErpCustomerDO customer = BeanUtils.toBean(createReqVO, ErpCustomerDO.class);
        customer.setAlias(PinyinUtil.getFirstLetter(customer.getName(), ""));
        customerMapper.insert(customer);

        if (StringUtils.isNotBlank(createReqVO.getCarNumbers())) {
            List<ErpCustomerCarNumberDO> carNumberList = new ArrayList<>();
            String[] carNumbers = createReqVO.getCarNumbers().split(",");
            for (String carNumber : carNumbers) {
                ErpCustomerCarNumberDO carNumberDO = new ErpCustomerCarNumberDO()
                        .setCustomerId(customer.getId())
                        .setCarNumber(carNumber);

                carNumberList.add(carNumberDO);
            }

            if (!carNumberList.isEmpty()) {
                customerCarNumberMapper.insertBatch(carNumberList);
            }
        }
        // 返回
        return customer.getId();
    }

    @Override
    @Transactional
    public void updateCustomer(ErpCustomerSaveReqVO updateReqVO) {
        // 校验存在
        validateCustomerExists(updateReqVO.getId());
        // 更新
        ErpCustomerDO updateObj = BeanUtils.toBean(updateReqVO, ErpCustomerDO.class);
        updateObj.setAlias(PinyinUtil.getFirstLetter(updateReqVO.getName(), ""));
        customerMapper.updateById(updateObj);

        List<ErpCustomerCarNumberDO> oldList = customerCarNumberMapper.selectList(
                new LambdaQueryWrapperX<ErpCustomerCarNumberDO>()
                        .eq(ErpCustomerCarNumberDO::getCustomerId, updateReqVO.getId())
        );

        List<ErpCustomerCarNumberDO> newList = new ArrayList<>();
        for (String s : updateReqVO.getCarNumbers().split(",")) {
            ErpCustomerCarNumberDO carNumberDO = new ErpCustomerCarNumberDO()
                    .setCustomerId(updateReqVO.getId())
                    .setCarNumber(s);
            newList.add(carNumberDO);
        }

        List<List<ErpCustomerCarNumberDO>> diffList = diffList(oldList, newList,
                (oldVal, newVal) -> oldVal.getCarNumber().equals(newVal.getCarNumber())
        );
        if (CollUtil.isNotEmpty(diffList.get(0))) {
            customerCarNumberMapper.insertBatch(diffList.get(0));
        }
        if (CollUtil.isNotEmpty(diffList.get(1))) {
            customerCarNumberMapper.updateBatch(diffList.get(1));
        }
        if (CollUtil.isNotEmpty(diffList.get(2))) {
            customerCarNumberMapper.delete(
                    new LambdaQueryWrapperX<ErpCustomerCarNumberDO>()
                            .in(ErpCustomerCarNumberDO::getCarNumber, diffList.get(2).stream().map(ErpCustomerCarNumberDO::getCarNumber).toList())
            );
        }
    }

    @Override
    public void deleteCustomer(Long id) {
        // 校验存在
        validateCustomerExists(id);
        // 删除
        customerMapper.deleteById(id);
    }

    private void validateCustomerExists(Long id) {
        if (customerMapper.selectById(id) == null) {
            throw exception(CUSTOMER_NOT_EXISTS);
        }
    }

    @Override
    public ErpCustomerDO getCustomer(Long id) {
        return customerMapper.selectById(id);
    }

    @Override
    public ErpCustomerDO validateCustomer(Long id) {
        ErpCustomerDO customer = customerMapper.selectById(id);
        if (customer == null) {
            throw exception(CUSTOMER_NOT_EXISTS);
        }
        if (CommonStatusEnum.isDisable(customer.getStatus())) {
            throw exception(CUSTOMER_NOT_ENABLE, customer.getName());
        }
        return customer;
    }

    @Override
    public List<ErpCustomerDO> getCustomerList(Collection<Long> ids) {
        return customerMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<ErpCustomerDO> getCustomerPage(ErpCustomerPageReqVO pageReqVO) {
        return customerMapper.selectPage(pageReqVO);
    }

    @Override
    public List<ErpCustomerDO> getCustomerListByStatus(Integer status) {
        return customerMapper.selectListByStatus(status);
    }

    @Override
    public List<ErpCustomerCarNumberDO> getCustomerCarNumberList(Collection<Long> customerIds) {
//        return customerCarNumberMapper.selectList(
//                new LambdaQueryWrapperX<ErpCustomerCarNumberDO>()
//                        .in(ErpCustomerCarNumberDO::getCustomerId, customerIds)
//        );
        return customerCarNumberMapper.selectListByCustomerIds(customerIds);
    }

    @Override
    public List<ErpCustomerCarNumberDO> getCustomerCarNumberList(Long customerId) {
        return customerCarNumberMapper.selectList(
                new LambdaQueryWrapperX<ErpCustomerCarNumberDO>()
                        .eq(ErpCustomerCarNumberDO::getCustomerId, customerId)
        );
//        return customerCarNumberMapper.selectListByCustomerId(customerId);
    }

    @Override
    public PageResult<ErpCustomerMoreRespVO> getCustomerMorePage(ErpCustomerMorePageReqVO pageReqVO) {
        PageResult<ErpCustomerMoreRespVO> pageResult = new PageResult<>();
        List<ErpCustomerMoreRespVO> list = new ArrayList<>();
        if (pageReqVO.getCustomerName() != null || pageReqVO.getMobile() != null) {
            PageResult<ErpCustomerDO> customerPage = customerMapper.selectPage(pageReqVO,
                    new LambdaQueryWrapperX<ErpCustomerDO>()
                            .likeIfPresent(ErpCustomerDO::getMobile, pageReqVO.getMobile())
                            .or(
                                    q ->
                                            q.like(ErpCustomerDO::getName, pageReqVO.getCustomerName())
                                                    .or()
                                                    .like(ErpCustomerDO::getAlias, pageReqVO.getCustomerName())
                            )
            );
            if (!customerPage.getList().isEmpty()) {
                Map<Long, List<ErpCustomerCarNumberDO>> carNumberMap = getCustomerAllCarNumberMap(
                        convertSet(customerPage.getList(), ErpCustomerDO::getId));

                for (ErpCustomerDO customer : customerPage.getList()) {
                    ErpCustomerMoreRespVO respVO = new ErpCustomerMoreRespVO()
                            .setCustomerId(customer.getId())
                            .setCustomerName(customer.getName())
                            .setMobile(customer.getMobile());

                    List<ErpCustomerCarNumberDO> carNumberList = carNumberMap.get(customer.getId());
                    if (CollUtil.isNotEmpty(carNumberList)) {
                        respVO.setCarNumberList(carNumberList.stream().filter(carNumber -> !carNumber.getDeleted()).map(carNumber -> new ErpCustomerMoreRespVO.Item()
                                .setCarNumberId(carNumber.getId())
                                .setCarNumber(carNumber.getCarNumber())
                        ).toList());
                    }

                    list.add(respVO);
                }
            }
        } else if (pageReqVO.getCarNumber() != null) {
            PageResult<ErpCustomerCarNumberDO> carNumberPage = customerCarNumberMapper.selectPage(pageReqVO,
                    new LambdaQueryWrapperX<ErpCustomerCarNumberDO>()
                            .likeIfPresent(ErpCustomerCarNumberDO::getCarNumber, pageReqVO.getCarNumber())
                            .and(q ->
                                q.eq(ErpCustomerCarNumberDO::getDeleted, 1)
                                        .or()
                                        .eq(ErpCustomerCarNumberDO::getDeleted, 0)
                            )
            );
            if (!carNumberPage.getList().isEmpty()) {
                Map<Long, ErpCustomerDO> customerMap = getCustomerMap(
                        convertSet(carNumberPage.getList(), ErpCustomerCarNumberDO::getCustomerId)
                );

                for (ErpCustomerCarNumberDO carNumberDO : carNumberPage.getList()) {
                    ErpCustomerDO customer = customerMap.get(carNumberDO.getCustomerId());
                    if (customer != null && customer.getId() != null) {
                        List<ErpCustomerMoreRespVO.Item> carNumberList = new ArrayList<>();
                        carNumberList.add(new ErpCustomerMoreRespVO.Item()
                                .setCarNumberId(carNumberDO.getId())
                                .setCarNumber(carNumberDO.getCarNumber()));
                        ErpCustomerMoreRespVO respVO = new ErpCustomerMoreRespVO()
                                .setCustomerId(customer.getId())
                                .setCustomerName(customer.getName())
                                .setMobile(customer.getMobile())
                                .setCarNumberList(carNumberList);

                        list.add(respVO);
                    }
                }
            }
        }
        pageResult.setList(list);
        return pageResult;
    }
}